package com.berte.ui;

import com.berte.data.SaveData;
import com.berte.uart.Uart;
import com.berte.uart.UartRecv;
import com.sun.org.apache.bcel.internal.generic.SWITCH;

import javax.swing.*;
import javax.swing.event.AncestorListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import java.awt.event.*;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;

public class uart_ui {
    private JPanel RootJPanel;
    private JPanel SettingJPanel;
    private JPanel DisplayJPanel;
    private JPanel AddDataJPanel;
    private JComboBox PortComboBox;
    private JComboBox BaudRateComboBox;
    private JComboBox DataBitsComboBox;
    private JComboBox StopBitsComboBox;
    private JComboBox ParityComboBox;
    private JLabel PortLabel;
    private JLabel BaudRateLabel;
    private JLabel DataBits;
    private JButton ConnectButton;
    private JRadioButton RTSRadioButton;
    private JRadioButton DTRRadioButton;
    private JRadioButton RecvASCIIRadioButton;
    private JCheckBox SaveCheckBox;
    private JRadioButton RecvHEXRadioButton;
    private JRadioButton SendASCIIRadioButton;
    private JRadioButton SendHEXRadioButton;
    private JCheckBox EnterCheckBox;
    private JCheckBox LineCheckBox;
    private JComboBox DecodeComboBox;
    private JTextArea RecvtextArea;
    private JButton ClearButton;
    private JButton SendButton;
    private JButton AddDataButton;
    private JLabel StopBitsJLabel;
    private JLabel ParityJLabel;
    private JLabel DecodeJLabel;
    private JPanel RecvSetingJPanel;
    private JPanel SendSetingJPanel;
    private JScrollPane rxJScrollPane;
    private JTextArea SendtextArea;
    private JScrollPane txJScrollPane;

    //创建一个定时器用于扫描串口端口
    private Timer PortScanTimer;
    private Uart uart;
    private String[] uartlist = null;
    private String[] uartlist_old = null;
    private String uartName;
    private Boolean isConnected = false;

    //用于接收的变量
    private Queue<Byte> uartRecvQueue = new LinkedList<Byte>();

    //创建串口接收的线程
    private UartRecv uartRecv = new UartRecv();
    private Thread threadRecvUart = new Thread(uartRecv, "uartRecv");

    //创建保存数据并显示的线程
    private SaveData saveData = new SaveData();
    private Thread threadSaveData = new Thread(saveData, "saveData");


    //    构造方法
    public uart_ui() {
        uart = new Uart();
        PortScanTimer = new Timer(300, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //定时器事件
                uartlist = uart.getUartlist();
                //仅当串口设备有变化时，更新设备列表
                if (!Arrays.equals(uartlist_old, uartlist)) {
                    uartlist_old = uartlist;
                    PortComboBox.removeAllItems();
                    for (String s : uartlist) {
                        PortComboBox.addItem(s);
                    }
                }
            }
        });

//        连接按钮按下事件
        ConnectButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (!isConnected) {
                    ConnectButtonActionHandler();
                } else {
                    DisConnectButtonActionHandler();
                }
            }
        });

//        接收文本框最大显示201行
        RecvtextArea.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                if (RecvtextArea.getLineCount() >= 51) {
                    new Thread(() -> {
                        synchronized (RecvtextArea) {
                            for (int i = 0; i < RecvtextArea.getLineCount() - 50; i++) {
                                try {
                                    RecvtextArea.replaceRange("", 0, RecvtextArea.getLineEndOffset(0));
                                } catch (BadLocationException a) {
                                    a.printStackTrace();
                                }
                            }
                        }
                    }).start();
                }
            }

            @Override
            public void removeUpdate(DocumentEvent e) {

            }

            @Override
            public void changedUpdate(DocumentEvent e) {

            }
            /*public void insertUpdate(DocumentEvent evt){
                SwingUtilities.invokeLater(new Runnable(){
                    public void run(){
                        if(RecvtextArea.getLineCount() == 51){
                            try {
                                RecvtextArea.replaceRange("",0,RecvtextArea.getLineEndOffset(0));
                            } catch (BadLocationException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                });
            }*/
        });

//        发送按钮点击事件
        SendButton.addActionListener((ActionEvent e) -> {
            SendButtonHandler();
        });
        RecvtextArea.setEditable(false); //将接收框设置为不可编辑

        setDefaultParam();  //设置默认参数
        PortScanTimer.start(); //启动端口扫描定时器

        //先中断两个线程
        uartRecv.running = false;
        saveData.running = false;

        //启动线程
        threadRecvUart.start();
        threadSaveData.start();
    }

    public JPanel getRootJPanel() {
        return RootJPanel;
    }

    private void setDefaultParam() {
        //设置默认串口参数
        BaudRateComboBox.setSelectedItem("115200");
        DataBitsComboBox.setSelectedItem("8");
        StopBitsComboBox.setSelectedItem("1");
        ParityComboBox.setSelectedItem("None");

        //设置单选按钮
        RecvASCIIRadioButton.setSelected(true);
        DTRRadioButton.setSelected(true);
        SendASCIIRadioButton.setSelected(true);

        DecodeComboBox.setSelectedItem("UTF-8");
    }

    //连接按钮按下处理方法
    private void ConnectButtonActionHandler() {

        //获取uart的参数
        uartName = (String) PortComboBox.getSelectedItem();
        uart.setBaudRate(Integer.parseInt((String) BaudRateComboBox.getSelectedItem(), 10));
        uart.setDataBits(Integer.parseInt((String) DataBitsComboBox.getSelectedItem(), 10));
        uart.setStopBits(Integer.parseInt((String) StopBitsComboBox.getSelectedItem(), 10));
        switch ((String) ParityComboBox.getSelectedItem()) {
            case "Even":
                uart.setParity(Uart.PARITY_EVEN);
                break;
            case "Odd":
                uart.setParity(Uart.PARITY_ODD);
                break;
            case "None":
                uart.setParity(Uart.PARITY_NONE);
                break;
        }

        if (RTSRadioButton.isSelected()) {
            uart.setSetRTS(true);
        } else {
            uart.setSetRTS(false);
        }

        if (DTRRadioButton.isSelected()) {
            uart.setSetDTR(true);
        } else {
            uart.setSetDTR(false);
        }

        //参数均设置完成，进行连接所选串口
        if (!uart.open(uartName)) {
            /*串口连接失败
            弹窗提示*/
            JOptionPane.showMessageDialog(RootJPanel, "参数错误或者当前端口被占用", "错误 ", JOptionPane.ERROR_MESSAGE);
            return;
        }

        PortScanTimer.stop(); //用于扫描端口设备的定时器关闭
        ConnectButton.setText("已连接");
        isConnected = true;

        //正确连接以后，开启串口接收线程
        uartRecv.setUart(uart); //将所连接的串口传递给串口接收的线程
        uartRecv.setUartRecvQueue(uartRecvQueue);   //将接收队列传递给串口接收的线程

        saveData.setRecvQueue(uartRecvQueue);   //将接收队列传递给保存线程
        saveData.setRecvtextArea(RecvtextArea); //将显示区域窗口也传递给保存线程

        uartRecv.running = true;
        saveData.running = true;

    }

    //断开连接的处理
    private void DisConnectButtonActionHandler() {

        ConnectButton.setText("连接");
        isConnected = false;

        uartRecv.running = false;
        saveData.running = false;
        while (uartRecv.isRunning) ;
        while (saveData.isRunning) ;

        uartRecvQueue.clear();

        uart.close();
    }

    //    发送按键的处理
    private void SendButtonHandler() {
        //仅当连接成功时，才会响应此按钮
        if (isConnected) {

        } else {
            JOptionPane.showMessageDialog(RootJPanel, "端口未连接,请先连接端口！", "错误 ", JOptionPane.ERROR_MESSAGE);
        }
    }
}
